# fastapi_app/utils/lock.py
import asyncio
import uuid
import time
from contextlib import asynccontextmanager


@asynccontextmanager
async def redis_lock(
        redis: Redis,
        key: str,
        timeout: float = 5.0,
        retry_interval: float = 0.1
):
    identifier = str(uuid.uuid4())
    end_time = time.monotonic() + timeout

    while time.monotonic() < end_time:
        if await redis.set(key, identifier, nx=True, ex=timeout):
            try:
                yield True
            finally:
                # Lua脚本保证原子性释放
                lua = """
                if redis.call("get", KEYS[1]) == ARGV[1] then
                    return redis.call("del", KEYS[1])
                else
                    return 0
                end"""
                await redis.eval(lua, 1, key, identifier)
            return
        await asyncio.sleep(retry_interval)

    yield False